[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1 Programming definitions

The definitions in this section are only likely to be useful when you are writing nontrivial macros, not when writing a document.


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.1 Category codes

Plain TeX defines \active (as the number 13) for use in changing category codes. Although the author of The TeXbook has “intentionally kept the category codes numeric”, two other categories are commonly used: letters (category code 11) and others (12). Therefore, Eplain defines \letter and \other.

Sometimes it is cleaner to make a character active without actually writing a \catcode command. The \makeactive command takes a character as an argument to make active (and ignores following spaces). For example, here are two commands which both make \ active:

\makeactive`\\   \makeactive92

Usually, when you give a definition to an active character, you have to do so inside a group where you temporarily make the character active, and then give it a global definition (cf. the definition of \obeyspaces in The TeXbook). This is inconvenient if you are writing a long macro, or if the character already has a global definition you do not wish to transcend. Eplain provides \letreturn, which defines the usual end-of-line character to be the argument. For example:

\def\mymacro{… \letreturn\myreturn … }
\mymacro hello
there

The end-of-line between ‘hello’ and ‘there’ causes \myreturn to be expanded.

The TeXbook describes \uncatcodespecials, which makes all characters which are normally “special” into “other” characters, but the definition never made it into plain TeX. Eplain therefore defines it.

Finally, \percentchar expands into a literal ‘%’ character. This is useful when you \write TeX output to a file, and want to avoid spurious spaces. For example, Eplain writes a \percentchar after the definition of cross-references. The macros \lbracechar and \rbracechar expand similarly.


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.2 Allocation macros

Plain TeX provides macros that allocate registers of each primitive type in TeX, to prevent different sets of macros from using the same register for two different things. The macros are all named starting with ‘new’, e.g., \newcount allocates a new “count” (integer) register. Such allocations are usually needed only at the top level of some macro definition file; therefore, plain TeX makes the allocation registers \outer, to help find errors. (The error this helps to find is a missing right brace in some macro definition.)

Sometimes, however, it is useful to allocate a register as part of some macro. An outer control sequence cannot be used as part of a macro definition (or in a few other contexts: the parameter text of a definition, an argument to a definition, the preamble of an alignment, or in conditional text that is being skipped). Therefore, Eplain defines “inner” versions of all the allocation macros, named with the prefix ‘inner’: \innernewbox, \innernewcount, \innernewdimen, \innernewfam, \innernewhelp, \innernewif, \innernewinsert, \innernewlanguage, \innernewread,
\innernewskip, \innernewtoks, \innernewwrite.

You can also define non-outer versions of other macros in the same way that Eplain defines the above. The basic macro is called \innerdef:

\innerdef \innername {outername}

The first argument (\innername) to \innerdef is the control sequence that you want to define. Any previous definition of \innername is replaced. The second argument (outername) is the characters in the name of the outer control sequence. (You can’t use the actual control sequence name, since it’s outer!)

If the outer control sequence is named \cs, and you want to define innercs as the inner one, you can use \innerinnerdef, which is just an abbreviation for a call to \innerdef. For example, these two calls are equivalent:

\innerdef\innerproclaim{proclaim}
\innerinnerdef{proclaim}

[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.3 Iteration

You can iterate through a comma-separated list of items with \for. Here is an example:

\for\name:=karl,kathy\do{%
   \message{\name}%
}%

This writes ‘karl’ and ‘kathy’ to the terminal. Spaces before or after the commas in the list, or after the :=, are not ignored.

\for expands the iterated values fully (with \edef), so this is equivalent to the above:

\def\namelist{karl,kathy}%
\for\name:=\namelist\do …

[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.4 Macro arguments

It is occasionally useful to redefine a macro that takes arguments to do nothing. Eplain defines \gobble, \gobbletwo, and \gobblethree to swallow one, two, and three arguments, respectively.

For example, if you want to produce a “short” table of contents—one that includes only chapters, say—the easiest thing to do is read the entire .toc file (@pxref{Contents}), and just ignore the commands that produce section or subsection entries. To be specific:

\let\tocchapterentry = \shorttocchapter
\let\tocsectionentry = \gobbletwo
\let\tocsubsectionentry = \gobbletwo
\readtocfile

(Of course, this assumes you only have chapters, sections, and subsections in your document.)

In addition, Eplain defines \eattoken to swallow the single following token, using \let. Thus, \gobble followed by ‘{…}’ ignores the entire brace-enclosed text. \eattoken followed by the same ignores only the opening left brace.

Eplain defines a macro \identity which takes one argument and expands to that argument. This may be useful if you want to provide a function for the user to redefine, but don’t need to do anything by default. (For example, the default definition of \eqconstruct (@pxref{Formatting equation references}) is \identity.)

You may also want to read an optional argument. The established convention is that optional arguments are put in square brackets, so that is the syntax Eplain recognizes. Eplain ignores space tokens before an optional argument, via \futurenonspacelet.

You test for an optional argument by using \@getoptionalarg. It takes one argument, a control sequence to expand after reading the argument, if present. If an optional argument is present, the control sequence \@optionalarg expands to it; otherwise, \@optionalarg is \empty. You must therefore have the category code of @ set to 11 (letter). Here is an example:

\catcode`@=\letter
\def\cmd{\@getoptionalarg\finishcmd}
\def\finishcmd{%
  \ifx\@optionalarg\empty
    % No optional argument present.
  \else
    % One was present.
  \fi
}

If an optional argument contains another optional argument, the inner one will need to be enclosed in braces, so TeX does not mistake the end of the first for the end of the second.


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.5 Converting to characters

Eplain defines \xrlabel to produce control sequence names for cross-reference labels, et al. This macro expands to its argument with an ‘_’ appended. (It does this because the usual use of \xrlabel is to generate a control sequence name, and we naturally want to avoid conflicts between control sequence names.)

Because \xrlabel is fully expandable, to make a control sequence name out of the result you need only do

\csname \xrlabel{label}\endcsname

The \csname primitive makes a control sequence name out of any sequence of character tokens, regardless of category code. Labels can therefore include any characters except for ‘\’, ‘{’, ‘}’, and ‘#’, all of which are used in macro definitions themselves.

\sanitize takes a control sequence as an argument and converts the expansion of the control sequence into a list of character tokens. This is the behavior you want when writing information like chapter titles to an output file. For example, here is part of the definition of \writenumberedtocentry; #2 is the title that the user has given.

…
\def\temp{#2}%
…
  \write\tocfile{%
    …
    \sanitize\temp
    …
  }%

[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.6 Expansion

This section describes some miscellanous macros for expansion, etc.


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.6.1 \csn and \ece

\csn{name} simply abbreviates \csname name \encsname, thus saving some typing. The extra level of expansion does take some time, though, so I don’t recommend it for an inner loop.

\ece{token}{name} abbreviates

\expandafter token \csname name \endcsname

For example,

\def\fontabbrevdef#1#2{\ece\def{@#1font}{#2}}
\fontabbrevdef{normal}{ptmr}

defines a control sequence \@normalfont to expand to ptmr.


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.6.2 \edefappend

\edefappend is a way of adding on to an existing definition. It takes two arguments: the first is the control sequence name, the second the new tokens to append to the definition. The second argument is fully expanded (in the \edef that redefines the control sequence).

For example:

\def\foo{abc}
\def\bar{xyz}
\edefappend\foo{\bar karl}

results in \foo being defined as ‘abcxyzkarl’.


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.6.3 Hooks

A hook is simply a name for a group of actions which is executed in certain places—presumably when it is most useful to allow customization or modification. TeX already provides many builtin hooks; for example, the \every … token lists are all examples of hooks.

Eplain provides several macros for adding actions to hooks. They all take two arguments: the name of the hook and the new actions.

hookaction name actions
hookappend name actions
hookprepend name actions

Each of these adds actions to the hook name. (Any previously-defined actions are retained.) name is not a control sequence, but rather the characters of the name.

hookactiononce name \cs

\hookactiononce adds cs to name, like the macros above, but first it adds

\global\let \cs \relax

to the definition of \cs. (This implies \cs must be a true expandable macro, not a control sequence \let to a primitive or some other such thing.) Thus, \cs is expanded the next time the hook name is run, but it will disappear after that.

The \global is useful because \hookactiononce is most useful when the grouping structure of the TeX code could be anything. Neither this nor the other hook macros do global assignments to the hook variable itself, so TeX’s usual grouping rules apply.

The companion macro to defining hook actions is \hookrun, for running them. This takes a single argument, the name of the hook. If no actions for the hook are defined, no error ensues.

Here is a skeleton of general \begin and \end macros that run hooks, and a couple of calls to define actions. The use of \hookprepend for the begin action and \hookappend for the end action ensures that the actions are executed in proper sequence with other actions (as long as the other actions use \hookprepend and \hookappend also).

\def\begin#1{ … \hookrun{begin} … }
\def\end#1{ … \hookrun{end} … }
\hookprepend{begin}\start_underline
\hookappend{end}\finish_underline

[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.6.4 Properties

A property is a name/value pair associated with another symbol, traditionally called an atom. Both atom and property names are control sequence names.

Eplain provides two macros for dealing with property lists: \setproperty and \getproperty.

\setproperty atom propname value

\setproperty defines the property property on the atom atom to be value. atom and propname can be anything acceptable to \csname. value can be anything.

\getproperty atom propname

\getproperty expands to the value stored for propname on atom. If propname is undefined, it expands to nothing (i.e., \empty).

The idea of properties originated in Lisp (I believe). There, the implementation truly does associate properties with atoms. In TeX, where we have no builtin support for properties, the association is only conceptual.

The following example typesets ‘xyz’.

\setproperty{a}{pr}{xyz}
\getproperty{a}{pr}

[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.6.5 \expandonce

\expandonce is defined as \expandafter\noexpand. Thus, \expandonce token expands token once, instead of to TeX primitives. This is most useful in an \edef.

For example, the following defines \temp to be \foo, not ‘abc’.

\def\foo{abc}
\def\bar{\foo}
\edef\temp{\expandonce\bar}

[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.6.6 \ifundefined

\ifundefined{cs} t \else f \fi expands the t text if the control sequence \cs is undefined or has been \let to \relax, and the f text otherwise.

Since \ifundefined is not a primitive conditional, it cannot be used in places where TeX might skip tokens “at high speed”, e.g., within another conditional—TeX can’t match up the \if’s and \fi’s.

This macro was taken directly from The TeXbook, page 308.


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.6.7 \futurenonspacelet

The \futurelet primitive allows you to look at the next token from the input. Sometimes, though, you want to look ahead ignoring any spaces. This is what \futurenonspacelet does. It is otherwise the same as \futurelet: you give it two control sequences as arguments, and it assigns the next nonspace token to the first, and then expands the second. For example:

\futurenonspacelet\temp\finishup
\def\finishup{\ifx\temp …}

[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.7 Obeying spaces

\obeywhitespace makes both end-of-lines and space characters in the input be respected in the output. Unlike plain TeX’s \obeyspaces, even spaces at the beginnings of lines turn into blank space.

By default, the size of the space that is produced by a space character is the natural space of the current font, i.e., what \ produces.

Ordinarily, a blank line in the input produces as much blank vertical space as a line of text would occupy. You can adjust this by assigning to the parameter \blanklineskipamount: if you set this negative, the space produced by a blank line will be smaller; if positive, larger.

Tabs are not affected by this routine. In particular, if tabs occur at the beginning of a line, they will disappear. (If you are trying to make TeX do the “right thing” with tabs, don’t. Use a utility program like expand instead.)


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.8 Writing out numbers

\numbername produces the written-out form of its argument, i.e., ‘zero’ through ‘ten’ for the numbers 0–10, and numerals for all others.


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.9 Mode-specific penalties

TeX’s built-in \penalty command simply appends to the current list, no matter what kind of list it is. You might intend a particular penalty to always be a “vertical” penalty, however, i.e., appended to a vertical list. Therefore, Eplain provides \vpenalty and \hpenalty which first leave the other mode and then do \penalty.

More precisely, \vpenalty inserts \par if the current mode is horizontal, and \hpenalty inserts \leavevmode if the current mode is vertical. (Thus, \vpenalty cannot be used in math mode.)


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.10 Auxiliary files

It is common to write some information out to a file to be used on a subsequent run. But when it is time to read the file again, you only want to do so if the file actually exists. \testfileexistence is given an argument which is appended to \jobname, and sets the conditional \iffileexists appropriately.

For example:

\testfileexistence{toc}%
\iffileexists
   \input \jobname.toc
\fi

[Top] [Contents] [Index] [ ? ]

About This Document

This document was generated on January 31, 2023 using texi2html 5.0.

The buttons in the navigation panels have the following meaning:

Button Name Go to From 1.2.3 go to
[ << ] FastBack Beginning of this chapter or previous chapter 1
[ < ] Back Previous section in reading order 1.2.2
[ Up ] Up Up section 1.2
[ > ] Forward Next section in reading order 1.2.4
[ >> ] FastForward Next chapter 2
[Top] Top Cover (top) of document  
[Contents] Contents Table of contents  
[Index] Index Index  
[ ? ] About About (help)  

where the Example assumes that the current position is at Subsubsection One-Two-Three of a document of the following structure:


This document was generated on January 31, 2023 using texi2html 5.0.